﻿using Cloud.Core.Cache;
using Cloud.Framework.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

namespace Cloud.Framework.Filter
{
    //全局权限过滤器--所有子系统共用
    public class GlobalAuthorizeFilter : IAuthorizationFilter
    {
        private readonly ICacheManager _cacheManager;
        public IConfiguration Configuration { get; }
        public GlobalAuthorizeFilter(IConfiguration configuration, ICacheManager _cacheManager)
        {
            this.Configuration = configuration;
            this._cacheManager = _cacheManager;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
        

            if (HasActionAttribute<PublicAction>(context))//不需要登录
            {
                return;
            }
            var conf = (IConfiguration)context.HttpContext.RequestServices.GetService(typeof(IConfiguration));
            var cookieKey = conf.GetSection("ProjectSetting")["CookieKey"];
            string cookieValue = null;
            context.HttpContext.Request.Cookies.TryGetValue(cookieKey, out cookieValue);
            if (string.IsNullOrEmpty(cookieValue))
            {
                string msg = "你没有登录或者登录状态失效，请重新登录";
                ErrorReturn(context, msg,400);
                return;
            }
            //更新cookie--模拟滑动过期
            context.HttpContext.Response.Cookies.Append(cookieKey, cookieValue, new CookieOptions
            {
                Expires = DateTime.Now.AddMinutes(conf.GetSection("ProjectSetting")["SessionTimeOut"].ToInt()),
                HttpOnly = true
            });

            //获取用户对于的缓存KEY
            string userCacheKey = cookieValue;
            var currentSysUser =_cacheManager.Get<CurrentSysUser>(userCacheKey);
            //2 用户没登录 或 session失效
            if (currentSysUser == null)
            {
                string msg = "你没有登录或者登录状态失效，请重新登录";
                ErrorReturn(context, msg,400);
                return;
            }
            //暂时存放--以便于读取
            context.HttpContext.Items["currentUser"] = currentSysUser;
            if (currentSysUser.IsAdmin)
            {
                return;
            }
            if (HasActionAttribute<LoginAction>(context))//只需要登录，不需要授权
            {
                return;
            }
            var permissions = _cacheManager.Get<List<CurrentSysUserPermission>>(currentSysUser.PermissionCacheKey);
            var values = context.ActionDescriptor.RouteValues.Values;
            string controllerName = null;
            string actionName = null;
            int i = 0;
            foreach (var item in values)
            {
                if (i == 0)
                {
                    actionName = item;
                }
                if (i == 1)
                {
                    controllerName = item;
                }
                i++;
            }
            bool hasPermission = permissions.Where(c => c.action == actionName && c.controller == controllerName).Any();

            if (hasPermission == false)
            {

                ErrorReturn(context, "菜单【/" + controllerName + "/" + actionName + "】没有权限，请联系管理员", 401);
            }
        }

        private static void ErrorReturn(AuthorizationFilterContext filterContext, string msg, int code)
        {
            
            if (IsAjax(filterContext))
            {
                msg = WebUtility.HtmlDecode(WebUtility.UrlDecode(msg ?? ""));
                var data = new { msg = msg, code = code };
                filterContext.Result = new JsonResult(data);
            }
            else
            {
                msg = WebUtility.HtmlEncode(WebUtility.UrlEncode(msg ?? ""));
                filterContext.Result = new RedirectResult("/Account/Login?error=" + msg);
            }
        }
        public static bool IsAjax(AuthorizationFilterContext filterContext )
        {
            bool result = false;

            var xreq = filterContext.HttpContext.Request.Headers.ContainsKey("x-requested-with");
            if (xreq)
            {
                result = filterContext.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest";
            }

            return result;
        }
        public bool HasActionAttribute<T>(AuthorizationFilterContext context) where T : ActionFilterAttribute
        {
            bool isHas = false;
            var allFilters = context.Filters;
            foreach (var item in allFilters)
            {
                if (item.GetType().Equals(typeof(T)))
                {
                    isHas = true;
                    break;
                }
            }
            return isHas;

        }


       
    }
}
